package tools;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import models.HttpResponse;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Date;
import java.util.Map;
import java.util.Objects;

/**
 * Created by yangxianming on 2017/3/16.
 * 文件如何上传，例：
 * 参数param设置
 * SONObject fileObject = new JSONObject();
 * fileObject.put("fileName", "xxx.jmx");
 * fileObject.put("nameType", "file");
 * JSONObject parJson = new JSONObject();
 * parJson.put("fileObject", fileObject);
 * 头部设置
 * JSONObject header = new JSONObject();
 * header.put("Content-Type", "multipart/form-data;charset=UTF-8;");
 * 构造函数指定文件位置
 * Http http = new Http("D:\\javaWorkSpace\\testServer2\\web\\jmeterScript\\koufu\\");
 */
public class Http {
    private HttpResponse httpResponse = new HttpResponse();
    private String filePath;

    public Http(){}

    public Http(String filePath){
        //当需要文件上传时，需要初始化这个构造函数确定文件存放的位置
        this.filePath = filePath;
    }

    public HttpResponse sendRequest (String method, JSONObject headers, String url, String param, int timeout){
        return send(method, headers, url, param, timeout);
    }

    public HttpResponse sendRequest (String method, JSONObject headers, String url, String param){
        return send(method, headers, url, param, 120000);
    }

    private HttpResponse send (String method, JSONObject headers, String url, String param, int timeout){
        String result = "";
        OutputStreamWriter out;
        BufferedReader in = null;
        method = method.toUpperCase();
        boolean isFileUpload = false;
        String boundary = "yangxianmingtest" + new Date().getTime();
        DataOutputStream dos;

        try {
            String urlNameString;
            //get请求的url
            if (Objects.equals(method, "GET")){
                urlNameString = url + "?" + param;
            }else {
                urlNameString = url;
            }

            URL realUrl = new URL(urlNameString);
            // 打开和URL之间的连接
            HttpURLConnection connection = (HttpURLConnection)realUrl.openConnection();
            connection.setDoInput(true);
            connection.setDoOutput(true);
            connection.setConnectTimeout(timeout);
            connection.setReadTimeout(timeout);

            // 设置通用的请求属性
            if (null != headers){
                isFileUpload = headers.getString("Content-Type").contains("multipart/form-data");

                for (Map.Entry me: headers.entrySet()){
                    if (Objects.equals(String.valueOf(me.getKey()), "Content-Type") && isFileUpload){
                        connection.setRequestProperty(String.valueOf(me.getKey()), String.valueOf(me.getValue()) + "boundary=" + boundary);
                        continue;
                    }
                    connection.setRequestProperty(String.valueOf(me.getKey()), String.valueOf(me.getValue()));
                }
            }

            // 设置请求方式
            if (Objects.equals(method, "PATCH")){
                connection.setRequestProperty("X-HTTP-Method-Override", "PATCH");
                connection.setRequestMethod("POST");
            }else {
                connection.setRequestMethod(method);
            }

//            connection.connect();
            // 建立实际的链接
            if (!Objects.equals(method, "GET")){
                //如果是文件上传文件读取在这里
                if (isFileUpload){

                    dos = new DataOutputStream(connection.getOutputStream());
                    JSONObject parJSON = JSON.parseObject(param);
                    JSONObject fileObject = parJSON.getJSONObject("fileObject");    //获取文件相关的json参数
                    JSONObject par = parJSON.getJSONObject("par");                  //这里获取普通的参数
                    String fileName = fileObject.getString("fileName");
                    String nameType = fileObject.getString("nameType");

                    //有参数的话
                    if (!Objects.equals(par, null)){
                        for (Map.Entry<String, Object> me: par.entrySet()){
                            String k = me.getKey();
                            String v = String.valueOf(me.getValue());
                            dos.writeBytes("--" + boundary + "\r\n");
                            dos.writeBytes("Content-Disposition: form-data; name=\"");
                            dos.writeBytes(k + "\r\n\r\n");
                            dos.writeBytes(v + "\r\n");
                        }
                    }

                    //如果有文件
                    byte[] fileBody = getFileBody(fileName);
                    if (fileBody.length > 0) {
                        String d = "--" + boundary + "\r\n";
                        d += "content-disposition: form-data; name=\"" + nameType + "\"; filename=\"" + fileName + "\"\r\n";
                        d += "Content-Transfer-Encoding: binary\r\n";
                        d += "Content-Type: \r\n\r\n";
                        dos.write(d.getBytes());
                        dos.write(fileBody);
                        dos.write(("\r\n").getBytes());
                    }
                    dos.writeBytes("--" + boundary + "--\r\n");
                    dos.flush();
                }else {
                    out = new OutputStreamWriter(connection.getOutputStream(), "UTF-8");
                    out.write(param);
                    out.flush();
                }

            }else {
                connection.connect();
            }
            //获取返回code
            httpResponse.setrCode(connection.getResponseCode());
            // 获取所有响应头字段
            httpResponse.setResponseHeader(connection.getHeaderFields());
            // 定义 BufferedReader输入流来读取URL的响应
            in = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"));
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
            httpResponse.setResponseResult(result);
        } catch (Exception e) {
            System.out.println("发送"+method+"请求出现异常！" + e);
//            e.printStackTrace();
//            httpResponse.setrCode(connection.getResponseCode());
            httpResponse.setResponseResult("method:" + method + " " + e.getMessage());
        }
        // 使用finally块来关闭输入流
        finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (Exception e2) {
                e2.printStackTrace();
            }
        }
        return httpResponse;
    }


    //请求参数需要特殊处理是在这里实现，如上传文件
    private byte[] getFileBody(String fileName){
        File file = new File(filePath + "/" + fileName);
        try {
            InputStream in = new FileInputStream(file);
            int len = 0;
            int t;
            byte[] bytes = new byte[(int)file.length()];
            while ((t = in.read()) != -1){
                bytes[len] = (byte)t;
                len++;
            }
            in.close();
            return bytes;
        }catch (IOException e){
            System.out.println(e.getMessage());
            return null;
        }
    }
}
